package com.futuremind.recyclerviewfastscroll.viewprovider;

import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.Component;


/**
 * Created by Michal on 05/08/16.
 * Animates showing and hiding elements of the {@link com.futuremind.recyclerviewfastscroll.FastScroller} (handle and bubble).
 * The decision when to show/hide the element should be implemented via {@link ViewBehavior}.
 */
public class VisibilityAnimationManager {

    protected final Component view;

    //protected AnimatorSet hideAnimator;
    protected AnimatorValue hideAnimator;
    protected AnimatorValue showAnimator;

    private float pivotXRelative;
    private float pivotYRelative;
    private int hideDelay;

    protected VisibilityAnimationManager(final Component view, int showAnimator, int hideAnimator, float pivotXRelative, float pivotYRelative, int hideDelay) {
        this.view = view;
        this.pivotXRelative = pivotXRelative;
        this.pivotYRelative = pivotYRelative;
        this.hideDelay = hideDelay;

        updatePivot();
    }

    public void show() {
        if (hideAnimator != null) {
            hideAnimator.cancel();
        }
        if (view.getVisibility() == Component.INVISIBLE) {
            view.setVisibility(Component.VISIBLE);
            updatePivot();
            view.setAlpha(0);
            view.setScaleX(0);
            view.setScaleY(0);
            showAnimator = new AnimatorValue();
            showAnimator.setDuration(200);
            showAnimator.setValueUpdateListener((animatorValue, v) -> {
                view.setAlpha(v);
                view.setScaleX(v);
                view.setScaleY(v);
            });
            showAnimator.start();
        }
    }

    public void hide() {
        updatePivot();
        if (hideAnimator != null) {
            hideAnimator.cancel();
        }
        view.setAlpha(1);
        view.setScaleX(1);
        view.setScaleY(1);
        hideAnimator = new AnimatorValue();
        hideAnimator.setDuration(200);
        hideAnimator.setDelay(hideDelay);
        hideAnimator.setValueUpdateListener((animatorValue, v) -> {
            view.setAlpha(1 - v);
            view.setScaleX(1 - v);
            view.setScaleY(1 - v);
        });
        hideAnimator.setStateChangedListener(new Animator.StateChangedListener() {
            boolean wasCanceled;

            @Override
            public void onStart(Animator animator) {

            }

            @Override
            public void onStop(Animator animator) {

            }

            @Override
            public void onCancel(Animator animator) {
                wasCanceled = true;
            }

            @Override
            public void onEnd(Animator animator) {
                if (!wasCanceled) view.setVisibility(Component.INVISIBLE);
                wasCanceled = false;
            }

            @Override
            public void onPause(Animator animator) {

            }

            @Override
            public void onResume(Animator animator) {

            }
        });
        hideAnimator.start();
    }


    protected void updatePivot() {
        view.setPivotX(pivotXRelative * view.getEstimatedWidth());
        view.setPivotY(pivotYRelative * view.getEstimatedHeight());
    }

    public static abstract class AbsBuilder<T extends VisibilityAnimationManager> {
        protected final Component view;
        // protected int showAnimatorResource = R.animator.fastscroll__default_show;
        protected int showAnimatorResource;
        // protected int hideAnimatorResource = R.animator.fastscroll__default_hide;
        protected int hideAnimatorResource;
        protected int hideDelay = 1000;
        protected float pivotX = 0.5f;
        protected float pivotY = 0.5f;

        public AbsBuilder(Component view) {
            this.view = view;
        }

        public AbsBuilder<T> withShowAnimator(int showAnimatorResource) {
            this.showAnimatorResource = showAnimatorResource;
            return this;
        }

        public AbsBuilder<T> withHideAnimator(int hideAnimatorResource) {
            this.hideAnimatorResource = hideAnimatorResource;
            return this;
        }

        public AbsBuilder<T> withHideDelay(int hideDelay) {
            this.hideDelay = hideDelay;
            return this;
        }

        public AbsBuilder<T> withPivotX(float pivotX) {
            this.pivotX = pivotX;
            return this;
        }

        public AbsBuilder<T> withPivotY(float pivotY) {
            this.pivotY = pivotY;
            return this;
        }

        public abstract T build();
    }

    public static class Builder extends AbsBuilder<VisibilityAnimationManager> {

        public Builder(Component view) {
            super(view);
        }

        public VisibilityAnimationManager build() {
            return new VisibilityAnimationManager(view, showAnimatorResource, hideAnimatorResource, pivotX, pivotY, hideDelay);
        }

    }

}
